package it.traveldreamWeb.employee;

import it.traveldream.beans.ExcursionManagerInterface;
import it.traveldream.beans.HotelManagerInterface;
import it.traveldream.beans.TransportMeanManagerInterface;
import it.traveldream.dto.ExcursionDTO;
import it.traveldream.dto.HotelDTO;
import it.traveldream.dto.HotelDTO.HotelRoomType;
import it.traveldream.dto.ProductDTO;
import it.traveldream.dto.ProductTypeDTO.ProductType;
import it.traveldream.dto.TransportMeanDTO;
import it.traveldream.exceptions.InvalidProductException;
import it.traveldream.exceptions.ProductNotFoundException;
import it.traveldreamWeb.shared.HotelRoom;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

@ManagedBean(name="modifyProductBean")
@ViewScoped
public class ModifyProductBean {

	private Long productId;
	private String productTypeId;
	private ProductDTO product;
	private TransportMeanDTO mean;
	private boolean isMean;
	private HotelDTO hotel;
	private List<HotelRoom> rooms;
	private boolean isHotel;
	private ExcursionDTO excursion;
	private boolean isExcursion;
	
	private String error;
	
	@EJB
	private TransportMeanManagerInterface meanMgr;
	@EJB
	private HotelManagerInterface hotelMgr;
	@EJB
	private ExcursionManagerInterface excMgr;
	
	@ManagedProperty(value="#{eSessionBean}")
	private EmployeeSessionBean session;
	
	public void init(){
		if (this.productId == null || this.productTypeId == null){
			ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
			try {
				String path = context.getRequestContextPath()+context.getRequestServletPath();
				context.redirect(path.replace("ModifyProduct.xhtml", "home.xhtml"));
			} catch (IOException e) {
				throw new RuntimeException();
			}
		}
		
		this.product = new ProductDTO();
		this.product.setProductId(this.productId);
		try{
		if (this.productTypeId.equals(ProductType.TRANSPORTMEAN.getID())){
			this.mean = this.meanMgr.getProduct(this.product);
			this.isMean = true;
			this.isHotel = false;
			this.isExcursion = false;
		} else 
		
		if (this.productTypeId.equals(ProductType.HOTEL.getID())){
			this.hotel = this.hotelMgr.getProduct(this.product);
			this.isMean = false;
			this.isHotel = true;
			this.isExcursion = false;	
		} else 
		
		if (this.productTypeId.equals(ProductType.EXCURSION.getID())){
			this.excursion = this.excMgr.getProduct(this.product);
			this.isMean = false;
			this.isHotel = false;
			this.isExcursion = true;
		}
		} catch (ProductNotFoundException e){
			this.setError("Invalid request. Wrong product?");
		} catch (Exception e){
			this.setError("Internal error. Please try again");
		}
	}

	public String saveMean(){
		this.setError("");
		try {
			if (this.mean.getLocation() == null){
				FacesMessage msg = new FacesMessage("Validation failed.", 
	                    "Select one location");
	            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
	            FacesContext.getCurrentInstance().addMessage("meanForm:destinationChoice", msg);
	            return null;
			}
			if (this.mean.getDeparture() == null){
				FacesMessage msg = new FacesMessage("Validation failed.", 
	                    "Select one departure");
	            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
	            FacesContext.getCurrentInstance().addMessage("meanForm:departureChoice", msg);
	            return null;
			}
			if (this.mean.getSpaces() == 0){
				FacesMessage msg = new FacesMessage("Validation failed.", 
	                    "Enter spaces");
	            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
	            FacesContext.getCurrentInstance().addMessage("meanForm:spaceSelection", msg);
	            return null;
			}
			
			this.meanMgr.updateProduct(this.mean);
			this.session.setSuccessMessage("Transport mean updated!");
			return "home?faces-redirect=true";
		} catch (InvalidProductException e) {
			this.setError("Internal error. Please try again");
			return null;
		} catch (ProductNotFoundException e) {
			this.setError("Invalid request. Wrong product?");
			return null;
		}
	}
	
	public String deleteMean(){
		this.setError("");
		try {
			this.meanMgr.deleteProduct(this.mean);
			this.session.setSuccessMessage("Transport mean deleted!");
			return "home?faces-redirect=true";
		} catch (ProductNotFoundException e) {
			this.setError("Invalid request. Wrong product?");
			return null;
		}
	}
	
	public String saveHotel(){
		this.setError("");
		try {
			if (this.hotel.getLocation() == null){
				FacesMessage msg = new FacesMessage("Validation failed.", 
	                    "Select one location");
	            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
	            FacesContext.getCurrentInstance().addMessage("hotelForm:locationHChoice", msg);
	            return null;
			}
			Map<HotelRoomType, Integer> rooms = new HashMap<>();
			Map<HotelRoomType, BigDecimal> prices = new HashMap<>();
			for (HotelRoom r : this.rooms){
				if (r.getTotalRooms() <= 0){
					FacesMessage msg = new FacesMessage("Validation failed.", 
		                    "Enter valid number");
		            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
		            FacesContext.getCurrentInstance().addMessage("hotelForm:rooms", msg);
					return null;
				}
				if (r.getPrice().signum() != 1){
					FacesMessage msg = new FacesMessage("Validation failed.", 
		                    "Enter valid price");
		            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
		            FacesContext.getCurrentInstance().addMessage("hotelForm:rooms", msg);
					return null;
				}
				rooms.put(r.getType(), r.getTotalRooms());
				prices.put(r.getType(), r.getPrice());
			}
			this.hotel.setRooms(rooms);
			this.hotel.setPrices(prices);
			this.hotelMgr.updateProduct(this.hotel);
			
			this.session.setSuccessMessage("Hotel updated!");
			return "home?faces-redirect=true";
		} catch (InvalidProductException e) {
			this.setError("Internal error. Please try again");
			return null;
		} catch (ProductNotFoundException e) {
			this.setError("Invalid request. Wrong product?");
			return null;
		}
	}
	
	public String deleteHotel(){
		this.setError("");
		try {
			this.hotelMgr.deleteProduct(this.hotel);
			this.session.setSuccessMessage("Hotel deleted!");
			return "home?faces-redirect=true";
		} catch (ProductNotFoundException e) {
			this.setError("Invalid request. Wrong product?");
			return null;
		}
	}

	public String saveExcursion(){
		this.setError("");
		try {
			if (this.excursion.getLocation() == null){
				FacesMessage msg = new FacesMessage("Validation failed.", 
	                    "Select one location");
	            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
	            FacesContext.getCurrentInstance().addMessage("excursionForm:locationEChoice", msg);
	            return null;
			}
			
			this.excMgr.updateProduct(this.excursion);
			
			this.session.setSuccessMessage("Excursion updated!");
			return "home?faces-redirect=true";
		} catch (InvalidProductException e) {
			this.setError("Internal error. Please try again");
			return null;
		} catch (ProductNotFoundException e) {
			this.setError("Invalid request. Wrong product?");
			return null;
		}
	}
	
	public String deleteExcursion(){
		this.setError("");
		try {
			this.excMgr.deleteProduct(this.excursion);
			this.session.setSuccessMessage("Excursion deleted!");
			return "home?faces-redirect=true";
		} catch (ProductNotFoundException e) {
			this.setError("Invalid request. Wrong product?");
			return null;
		}
	}
	
	public Long getProductId() {
		return this.productId;
	}

	public void setProductId(Long productId) {
		this.productId = productId;
	}

	public ProductDTO getProduct() {
		return this.product;
	}

	public void setProduct(ProductDTO product) {
		this.product = product;
	}

	public TransportMeanDTO getMean() {
		return this.mean;
	}

	public void setMean(TransportMeanDTO mean) {
		this.mean = mean;
	}

	public boolean getIsMean() {
		return this.isMean;
	}

	public HotelDTO getHotel() {
		return this.hotel;
	}

	public void setHotel(HotelDTO hotel) {
		this.hotel = hotel;
	}

	public List<HotelRoom> getRooms() {
		return this.rooms;
	}

	public void setRooms(List<HotelRoom> rooms) {
		this.rooms = rooms;
	}

	public boolean getIsHotel() {
		return this.isHotel;
	}

	public ExcursionDTO getExcursion() {
		return this.excursion;
	}

	public void setExcursion(ExcursionDTO excursion) {
		this.excursion = excursion;
	}

	public boolean getIsExcursion() {
		return this.isExcursion;
	}

	public String getProductTypeId() {
		return this.productTypeId;
	}

	public void setProductTypeId(String productTypeId) {
		this.productTypeId = productTypeId;
	}

	public String getError() {
		return this.error;
	}

	public void setError(String error) {
		this.error = error;
	}

	public void setSession(EmployeeSessionBean session) {
		this.session = session;
	}
}
